#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../src/parser/sql_parser.h"
#include "../include/gudb.h"

void test_basic_subquery_parsing() {
    printf("Testing basic subquery parsing...\n");
    
    // Test scalar subquery in SELECT list
    const char* sql1 = "SELECT name, (SELECT COUNT(*) FROM orders WHERE customer_id = customers.id) FROM customers";
    parser_t* parser1 = parser_create(sql1);
    statement_t* stmt1 = parser_parse_statement(parser1);
    
    assert(stmt1 != NULL);
    assert(stmt1->type == STMT_SELECT);
    
    // Check that we have a list with two expressions
    expression_t* select_list = stmt1->data.select.select_list;
    assert(select_list != NULL);
    assert(select_list->type == EXPR_LIST); // Multiple columns create a list
    assert(select_list->data.list.count == 2);
    
    // Check first column: name
    expression_t* first_expr = select_list->data.list.expressions[0];
    assert(first_expr != NULL);
    assert(first_expr->type == EXPR_COLUMN);
    
    // Check second column: subquery
    expression_t* second_expr = select_list->data.list.expressions[1];
    assert(second_expr != NULL);
    assert(second_expr->type == EXPR_SUBQUERY);
    
    // Verify the subquery is a valid SELECT statement
    statement_t* subquery = second_expr->data.subquery.query;
    assert(subquery != NULL);
    assert(subquery->type == STMT_SELECT);
    
    printf("Basic subquery parsing test passed!\n");
    
    statement_destroy(stmt1);
    parser_destroy(parser1);
}

void test_exists_subquery_parsing() {
    printf("Testing EXISTS subquery parsing...\n");
    
    // Test EXISTS subquery in WHERE clause
    const char* sql = "SELECT * FROM customers WHERE EXISTS (SELECT 1 FROM orders WHERE customer_id = customers.id)";
    parser_t* parser = parser_create(sql);
    statement_t* stmt = parser_parse_statement(parser);
    
    assert(stmt != NULL);
    assert(stmt->type == STMT_SELECT);
    
    // Check WHERE clause contains EXISTS function
    expression_t* where_clause = stmt->data.select.where_clause;
    assert(where_clause != NULL);
    assert(where_clause->type == EXPR_FUNCTION_CALL);
    assert(strcmp(where_clause->data.function_call.function_name, "EXISTS") == 0);
    assert(where_clause->data.function_call.arg_count == 1);
    
    // Check that the argument is a subquery
    expression_t* subquery_arg = where_clause->data.function_call.args[0];
    assert(subquery_arg != NULL);
    assert(subquery_arg->type == EXPR_SUBQUERY);
    
    // Verify the subquery is a valid SELECT statement
    statement_t* subquery = subquery_arg->data.subquery.query;
    assert(subquery != NULL);
    assert(subquery->type == STMT_SELECT);
    
    printf("EXISTS subquery parsing test passed!\n");
    
    statement_destroy(stmt);
    parser_destroy(parser);
}

void test_subquery_in_where_clause() {
    printf("Testing subquery in WHERE clause...\n");
    
    // Test subquery used for comparison
    const char* sql = "SELECT * FROM users WHERE age > (SELECT AVG(age) FROM users)";
    parser_t* parser = parser_create(sql);
    statement_t* stmt = parser_parse_statement(parser);
    
    assert(stmt != NULL);
    assert(stmt->type == STMT_SELECT);
    
    // Check WHERE clause is a binary comparison
    expression_t* where_clause = stmt->data.select.where_clause;
    assert(where_clause != NULL);
    assert(where_clause->type == EXPR_BINARY_OP);
    assert(where_clause->data.binary_op.operator == TOKEN_GREATER_THAN);
    
    // Check left side is column reference
    expression_t* left = where_clause->data.binary_op.left;
    assert(left != NULL);
    assert(left->type == EXPR_COLUMN);
    
    // Check right side is subquery
    expression_t* right = where_clause->data.binary_op.right;
    assert(right != NULL);
    assert(right->type == EXPR_SUBQUERY);
    
    // Verify the subquery is a valid SELECT statement
    statement_t* subquery = right->data.subquery.query;
    assert(subquery != NULL);
    assert(subquery->type == STMT_SELECT);
    
    printf("Subquery in WHERE clause test passed!\n");
    
    statement_destroy(stmt);
    parser_destroy(parser);
}

void test_complex_nested_subquery() {
    printf("Testing complex nested subquery...\n");
    
    // Test nested subqueries - using comparison instead of IN for now
    const char* sql = "SELECT name FROM customers WHERE id = (SELECT customer_id FROM orders WHERE total > (SELECT AVG(total) FROM orders) LIMIT 1)";
    parser_t* parser = parser_create(sql);
    statement_t* stmt = parser_parse_statement(parser);
    
    assert(stmt != NULL);
    assert(stmt->type == STMT_SELECT);
    
    // Check WHERE clause is a binary operation with EQUAL
    expression_t* where_clause = stmt->data.select.where_clause;
    assert(where_clause != NULL);
    assert(where_clause->type == EXPR_BINARY_OP);
    assert(where_clause->data.binary_op.operator == TOKEN_EQUAL);
    
    // Check right side is a subquery
    expression_t* right = where_clause->data.binary_op.right;
    assert(right != NULL);
    assert(right->type == EXPR_SUBQUERY);
    
    // Verify the outer subquery
    statement_t* outer_subquery = right->data.subquery.query;
    assert(outer_subquery != NULL);
    assert(outer_subquery->type == STMT_SELECT);
    
    // Check that the outer subquery has a WHERE clause with another subquery
    expression_t* outer_where = outer_subquery->data.select.where_clause;
    assert(outer_where != NULL);
    assert(outer_where->type == EXPR_BINARY_OP);
    
    // Check for the inner subquery
    expression_t* inner_right = outer_where->data.binary_op.right;
    assert(inner_right != NULL);
    assert(inner_right->type == EXPR_SUBQUERY);
    
    // Verify the inner subquery
    statement_t* inner_subquery = inner_right->data.subquery.query;
    assert(inner_subquery != NULL);
    assert(inner_subquery->type == STMT_SELECT);
    
    printf("Complex nested subquery test passed!\n");
    
    statement_destroy(stmt);
    parser_destroy(parser);
}

void test_subquery_error_handling() {
    printf("Testing subquery error handling...\n");
    
    // Test incomplete subquery (missing closing parenthesis)
    const char* sql1 = "SELECT name FROM customers WHERE EXISTS (SELECT 1 FROM orders";
    parser_t* parser1 = parser_create(sql1);
    statement_t* stmt1 = parser_parse_statement(parser1);
    
    // Should fail to parse
    assert(stmt1 == NULL);
    assert(parser1->error_message != NULL);
    printf("Incomplete subquery error: %s\n", parser1->error_message);
    
    parser_destroy(parser1);
    
    // Test invalid subquery (non-SELECT after EXISTS)
    const char* sql2 = "SELECT name FROM customers WHERE EXISTS (INSERT INTO test VALUES (1))";
    parser_t* parser2 = parser_create(sql2);
    statement_t* stmt2 = parser_parse_statement(parser2);
    
    // Should fail to parse
    assert(stmt2 == NULL);
    assert(parser2->error_message != NULL);
    printf("Invalid subquery error: %s\n", parser2->error_message);
    
    parser_destroy(parser2);
    
    printf("Subquery error handling test passed!\n");
}

void test_subquery_memory_management() {
    printf("Testing subquery memory management...\n");
    
    // Test that subqueries are properly cleaned up
    const char* sql = "SELECT (SELECT COUNT(*) FROM orders WHERE customer_id = c.id) FROM customers c WHERE EXISTS (SELECT 1 FROM orders WHERE customer_id = c.id)";
    parser_t* parser = parser_create(sql);
    statement_t* stmt = parser_parse_statement(parser);
    
    assert(stmt != NULL);
    assert(stmt->type == STMT_SELECT);
    
    // Parse was successful, now destroy and verify no memory leaks
    // (In a real test environment, you'd use valgrind or similar tools)
    statement_destroy(stmt);
    parser_destroy(parser);
    
    printf("Subquery memory management test passed!\n");
}

void print_expression_info(expression_t* expr, int depth) {
    if (!expr) return;
    
    for (int i = 0; i < depth; i++) printf("  ");
    
    switch (expr->type) {
        case EXPR_COLUMN:
            printf("COLUMN: %s.%s\n", 
                   expr->data.column.table_name ? expr->data.column.table_name : "NULL",
                   expr->data.column.column_name ? expr->data.column.column_name : "NULL");
            break;
        case EXPR_LITERAL:
            printf("LITERAL: %s\n", expr->data.literal.value);
            break;
        case EXPR_BINARY_OP:
            printf("BINARY_OP: %d\n", expr->data.binary_op.operator);
            print_expression_info(expr->data.binary_op.left, depth + 1);
            print_expression_info(expr->data.binary_op.right, depth + 1);
            break;
        case EXPR_FUNCTION_CALL:
            printf("FUNCTION: %s (%u args)\n", 
                   expr->data.function_call.function_name,
                   expr->data.function_call.arg_count);
            for (uint32_t i = 0; i < expr->data.function_call.arg_count; i++) {
                print_expression_info(expr->data.function_call.args[i], depth + 1);
            }
            break;
        case EXPR_SUBQUERY:
            printf("SUBQUERY: %s\n", 
                   expr->data.subquery.is_correlated ? "CORRELATED" : "UNCORRELATED");
            break;
        case EXPR_STAR:
            printf("STAR\n");
            break;
        default:
            printf("UNKNOWN TYPE: %d\n", expr->type);
            break;
    }
    
    if (expr->next) {
        print_expression_info(expr->next, depth);
    }
}

void test_detailed_subquery_structure() {
    printf("Testing detailed subquery structure...\n");
    
    const char* sql = "SELECT name, (SELECT COUNT(*) FROM orders WHERE customer_id = customers.id) as order_count FROM customers WHERE EXISTS (SELECT 1 FROM orders WHERE customer_id = customers.id)";
    parser_t* parser = parser_create(sql);
    statement_t* stmt = parser_parse_statement(parser);
    
    if (!stmt) {
        printf("Parse error: %s\n", parser->error_message);
        parser_destroy(parser);
        return;
    }
    
    printf("Successfully parsed SQL statement!\n");
    printf("Statement type: %d (STMT_SELECT = %d)\n", stmt->type, STMT_SELECT);
    
    printf("\nSELECT list structure:\n");
    print_expression_info(stmt->data.select.select_list, 0);
    
    printf("\nWHERE clause structure:\n");
    print_expression_info(stmt->data.select.where_clause, 0);
    
    statement_destroy(stmt);
    parser_destroy(parser);
    
    printf("Detailed subquery structure test passed!\n");
}

int main() {
    printf("=== GuDB Subquery Parsing Test ===\n\n");
    
    test_basic_subquery_parsing();
    printf("\n");
    
    test_exists_subquery_parsing();
    printf("\n");
    
    test_subquery_in_where_clause();
    printf("\n");
    
    test_complex_nested_subquery();
    printf("\n");
    
    test_subquery_error_handling();
    printf("\n");
    
    test_subquery_memory_management();
    printf("\n");
    
    test_detailed_subquery_structure();
    printf("\n");
    
    printf("=== All subquery parsing tests completed successfully! ===\n");
    
    return 0;
}